home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Magazin: Amiga-CD 1997 May & June
/
Amiga-CD 1997 #5-6.iso
/
emulatoren
/
frodov2.4
/
src
/
6581.asm
< prev
next >
Wrap
Assembly Source File
|
1996-12-08
|
10KB
|
533 lines
*
* 6581.asm - SID-Emulation
*
* Copyright (C) 1994-1996 by Christian Bauer
*
*
* Anmerkungen:
* ------------
*
* Funktionsprinzip:
* - Es bestehen vier Möglichkeiten zur SID-Emulation, die über das
* Flag UseSIDCard ausgewählt werden: Keine Emulation (d.h. kein Ton),
* die Verwendung der SID-Karte, die "6581sid.library" und die
* "playsid.library"
*
* SID-Karte:
* - Die SID-Karte enthält einen echten C64-SID, der im Adreßraum
* $a00001-$a00039 (Register an den ungeraden Adressen) eingeblendet
* ist (z.B. auf einer Zorro-II-Karte)
* - Wegen Timing-Problemen mit der Karte werden Lesezugriffe aus
* SID-Registern nur simuliert
* - Die Power-LED ist mit dem Reset-Eingang des SID verbunden,
* d.h. ein kurzes Aus- und Einschalten der LED setzt den SID
* zurück
*
* PlaySID:
* - Da die playsid.library keinen Befehl zum direkten Setzen von SID-
* Registern hat, wird ein Trick angewendet: Es wird ein Dummy-Modul
* installiert, dessen Play-Routine nur die Aufgabe hat, ein einziges
* SID-Register zu setzen. Schreibt der Prozessor in ein SID-Register,
* werden Registernummer und Wert in die Play-Routine im C64-RAM der
* playsid.library geschrieben und über ForwardSong ein Aufruf der
* Play-Routine erzwungen
*
MACHINE 68020
INCLUDE "exec/types.i"
INCLUDE "exec/macros.i"
INCLUDE "exec/nodes.i"
INCLUDE "libraries/playsidbase.i"
INCLUDE "libraries/playsid_lib.i"
INCLUDE "hardware/intbits.i"
XREF _SysBase
XREF _GfxBase
XREF _SID6581Base
XREF _PlaySidBase
XREF Random
XDEF Reset6581
XDEF ReadFrom6581
XDEF WriteTo6581
XDEF _PauseSound
XDEF _ResumeSound
XDEF _GetSIDDump
XDEF InitSID
XDEF ExitSID
XDEF ChangedSIDPrefs
XDEF SIDType ;Prefs
SECTION "text",CODE
*
* Definitionen
*
; SIDType
SIDTYPE_OFF = 0 ;Audio-Ausgabe aus
SIDTYPE_CARD = 1 ;SID-Karte
SIDTYPE_A64 = 2 ;6581sid.library
SIDTYPE_PSID = 3 ;playsid.library
; 6581sid.library
SID_AllocSID = -30
SID_FreeSID = -36
SID_Interrupt = -42
SID_Initialize = -48
SID_ResetSID = -54
SID_IRQOnOff = -60
SID_ReadReg = -72
SID_WriteReg = -78
; SID Handle Struktur
sid_Enabled = 4
sid_Filter = 5
sid_60Hz = 6
sid_RingQual = 7
sid_SyncQual = 8
sid_ADSRQual = 13
sid_IRQRate = 18
**
** SID-Emulation starten
**
InitSID move.w SIDType,CurrentSIDType
bsr OpenSID
st.b SIDInited
rts
**
** SID-Emulation beenden
**
ExitSID tst.b SIDInited
beq 1$
bsr CloseSID
1$ rts
**
** SID-Einstellungen wurde verändert
**
; Schließen und neu öffnen, wenn sich die Einstellungen geändert haben
ChangedSIDPrefs move.w SIDType,d0
cmp.w CurrentSIDType,d0
beq 1$
bsr CloseSID
move.w SIDType,CurrentSIDType
bsr OpenSID
moveq #0,d2
2$ move.w d2,d0
move.b (Registers,d0.w),d1
bsr WriteTo6581 ;SID-Register neu laden
addq.w #1,d2
cmp.w #24,d2
bne 2$
1$ rts
*
* Alles für SID-Emulation mit CurrentSIDType vorbereiten
*
OpenSID cmp.w #SIDTYPE_A64,CurrentSIDType
beq OpenA64
cmp.w #SIDTYPE_PSID,CurrentSIDType
beq OpenPSID
rts
OpenA64 move.l _SID6581Base,d0 ;6581sid.library offen?
beq 1$
move.l a6,-(sp) ;Ja, SIDHandle holen
move.l d0,a6
jsr SID_AllocSID(a6)
move.l d0,SIDHandle
beq 2$
move.l d0,a1 ;Parameter setzen
st.b sid_Enabled(a1)
clr.b sid_Filter(a1)
st.b sid_60Hz(a1)
move.b #48,sid_RingQual(a1)
move.b #48,sid_SyncQual(a1)
move.b #48,sid_ADSRQual(a1)
move.w #60,sid_IRQRate(a1)
jsr SID_Initialize(a6)
move.l SIDHandle,a1 ;SID anschalten
moveq #0,d0
jsr SID_IRQOnOff(a6)
move.l _SysBase,a6 ;VBI einrichten
lea VBInterrupt,a1
moveq #INTB_VERTB,d0
JSRLIB AddIntServer
2$ move.l (sp)+,a6
1$ rts
OpenPSID clr.b PSIDOpened
move.l _PlaySidBase,d0 ;playsid.library offen?
beq 1$
move.l a6,-(sp)
move.l d0,a6 ;Ja, Resourcen belegen
jsr _LVOAllocEmulResource(a6)
tst.l d0
bne 2$
lea PSIDHeader,a0 ;"Modul" setzen
move.l a0,a1
move.l #PSIDEnd-PSIDHeader,d0
jsr _LVOSetModule(a6)
moveq #1,d0 ;Und starten
jsr _LVOStartSong(a6)
tst.l d0
beq 3$
jsr _LVOFreeEmulResource(a6) ;Nicht gelungen
bra 2$
3$ bset #1,$bfe001 ;Filter aus
st.b PSIDOpened
2$ move.l (sp)+,a6
1$ rts
*
* SID-Emulation mit CurrentSIDType beenden
*
CloseSID cmp.w #SIDTYPE_A64,CurrentSIDType
beq CloseA64
cmp.w #SIDTYPE_PSID,CurrentSIDType
beq ClosePSID
rts
CloseA64 move.l SIDHandle,d0
beq 1$
move.l a6,-(sp)
move.l _SID6581Base,a6 ;SID abschalten
move.l d0,a1
moveq #-1,d0
jsr SID_IRQOnOff(a6)
move.l _SysBase,a6 ;VBI entfernen
lea VBInterrupt,a1
moveq #INTB_VERTB,d0
JSRLIB RemIntServer
move.l _SID6581Base,a6
move.l SIDHandle,a1 ;Und SIDHandle freigeben
jsr SID_FreeSID(a6)
clr.l SIDHandle
move.l (sp)+,a6
1$ rts
ClosePSID tst.b PSIDOpened
beq 1$
move.l a6,-(sp)
move.l _PlaySidBase,a6
jsr _LVOStopSong(a6) ;Alles freigeben
jsr _LVOFreeEmulResource(a6)
bclr #1,$bfe001 ;Filter an
clr.b PSIDOpened
move.l (sp)+,a6
1$ rts
*
* Interrupt-Routine
* a1: SIDHandle
*
IntProc move.l _SID6581Base,a6
jsr SID_Interrupt(a6)
moveq #0,d0 ;Nächsten Server aufrufen
rts
**
** Sound stummschalten
**
_PauseSound cmp.w #SIDTYPE_A64,CurrentSIDType
beq PauseA64
cmp.w #SIDTYPE_PSID,CurrentSIDType
beq PausePSID
rts
PauseA64 move.l SIDHandle,d0
beq 1$
move.l a6,-(sp)
move.l _SID6581Base,a6
move.l d0,a1
moveq #-1,d0
jsr SID_IRQOnOff(a6)
move.l (sp)+,a6
1$ rts
PausePSID tst.b PSIDOpened
beq 1$
move.l a6,-(sp)
move.l _PlaySidBase,a6
jsr _LVOPauseSong(a6)
move.l (sp)+,a6
1$ rts
**
** Sound wieder laut machen
**
_ResumeSound cmp.w #SIDTYPE_A64,CurrentSIDType
beq ResumeA64
cmp.w #SIDTYPE_PSID,CurrentSIDType
beq ResumePSID
rts
ResumeA64 move.l SIDHandle,d0
beq 1$
move.l a6,-(sp)
move.l _SID6581Base,a6
move.l d0,a1
moveq #0,d0
jsr SID_IRQOnOff(a6)
move.l (sp)+,a6
1$ rts
ResumePSID tst.b PSIDOpened
beq 1$
move.l a6,-(sp)
move.l _PlaySidBase,a6
jsr _LVOContinueSong(a6)
move.l (sp)+,a6
1$ rts
**
** SID zurücksetzen
**
Reset6581 lea Registers,a0
moveq #32/4-1,d0
1$ clr.l (a0)+
dbra d0,1$
clr.b LastSIDByte
cmp.w #SIDTYPE_CARD,CurrentSIDType
beq ResetCard
cmp.w #SIDTYPE_A64,CurrentSIDType
beq ResetA64
cmp.w #SIDTYPE_PSID,CurrentSIDType
beq ResetPSID
rts
ResetCard move.l a6,-(sp)
move.l _GfxBase,a6
JSRLIB WaitTOF
bset #1,$bfe001 ;LED aus
JSRLIB WaitTOF
bclr #1,$bfe001 ;LED an
move.l (sp)+,a6
rts
ResetA64 move.l SIDHandle,d0
beq 1$
move.l a6,-(sp)
move.l _SID6581Base,a6
move.l d0,a1
jsr SID_ResetSID(a6)
move.l (sp)+,a6
1$ rts
ResetPSID tst.b PSIDOpened
beq 1$
move.l a6,-(sp)
move.l _PlaySidBase,a6
jsr _LVOStopSong(a6)
moveq #1,d0
jsr _LVOStartSong(a6)
move.l (sp)+,a6
1$ rts
**
** SID-Status in Datenstruktur schreiben
**
_GetSIDDump move.l 4(sp),a1
lea Registers,a0
moveq #24,d0 ;freq_lo_1 bis mode_vol
1$ move.b (a0)+,(a1)+
dbra d0,1$
st (a1)+ ;pot_x
st (a1)+ ;pot_y
clr.b (a1)+ ;osc_3
clr.b (a1) ;env_3
rts
**
** Aus einem SID-Register lesen
** d0.w: Registernummer ($00-$1f)
** Rückgabe: d0.b: Byte
**
** Darf das obere Wort von d0 und d1 nicht verändern!
**
ReadFrom6581 cmp.b #$19,d0
beq ReadFF
cmp.b #$1a,d0
beq ReadFF
cmp.b #$1b,d0
beq ReadRnd
cmp.b #$1c,d0
beq ReadRnd
move.b LastSIDByte,d0
rts
ReadFF move.b #-1,d0 ;A/D-Wandler
clr.b LastSIDByte
rts
ReadRnd jsr Random
moveq #0,d1 ;MSW löschen
clr.b LastSIDByte
rts
**
** In ein SID-Register schreiben
** d0.w: Registernummer ($00-$1f)
** d1.b: Byte
**
** Darf das obere Wort von d0 und d1 nicht verändern!
**
WriteTo6581 move.b d1,(Registers,d0.w)
move.b d1,LastSIDByte
cmp.w #SIDTYPE_CARD,CurrentSIDType
beq WriteCard
cmp.w #SIDTYPE_A64,CurrentSIDType
beq WriteA64
cmp.w #SIDTYPE_PSID,CurrentSIDType
beq WritePSID
rts
WriteCard lea $a00001,a0 ;SID-Karte
move.b d1,(a0,d0.w*2)
rts
WriteA64 tst.l SIDHandle
beq 1$
move.l a6,-(sp)
move.l _SID6581Base,a6
move.l SIDHandle,a1 ;d0: Regnum, d1: Byte
jsr SID_WriteReg(a6)
move.l (sp)+,a6
moveq #0,d0
moveq #0,d1
1$ rts
WritePSID tst.b PSIDOpened
beq 1$
move.l a6,-(sp)
move.l _PlaySidBase,a6
move.l $15a(a6),a0 ;Code im C64-RAM der playsid.library ändern
move.b d0,$1004(a0)
move.b d1,$1002(a0)
moveq #1,d0 ;Aufruf der Play-Routine erzwingen
jsr _LVOForwardSong(a6)
move.l (sp)+,a6
moveq #0,d0
moveq #0,d1
1$ rts
**
** SID-Register (nur als Backup für SAM und Snapshots)
**
Registers ds.b 32
LastSIDByte ds.b 1 ;Letztes in den SID geschriebenes Byte
CNOP 0,4
**
** Konstanten
**
IntName dc.b "Frodo SID VBI",0
**
** Initialisierte Daten
**
SECTION "DATA",DATA
VBInterrupt dc.l 0,0
dc.b NT_INTERRUPT,0
dc.l IntName
SIDHandle dc.l 0 ;Handle für die 6581sid.library und Flag, daß sie verfügbar ist
dc.l IntProc
SIDType dc.w 0 ;Prefs: Art der SID-Emulation
PSIDHeader dc.b "PSID" ;Dummy-Modul-Header für playsid.library
dc.w 2
dc.w PSIDHeaderEnd-PSIDHeader
dc.w $1000 ;Load
dc.w $1000 ;Init
dc.w $1001 ;Play
dc.w 1
dc.w 1
dc.l 0
ds.b HEADERINFO_SIZE
ds.b HEADERINFO_SIZE
ds.b HEADERINFO_SIZE
dc.w 0
dc.l 0
PSIDHeaderEnd
;Init:
dc.b $60 ; rts
;Play:
dc.b $a9,0 ; lda #xx
dc.b $8d,0,$d4 ; sta $d4xx
dc.b $60 ; rts
PSIDEnd
**
** Nicht initialisierte Daten
**
SECTION "BSS",BSS
CurrentSIDType ds.w 1 ;Augenblicklicher SID-Typ
SIDInited ds.b 1 ;Flag: InitSID wurde aufgerufen
PSIDOpened ds.b 1 ;Flag: playsid.library ist initialisiert
END